# 06장 컨트롤러

Assembled by GimunLee


# 컨트롤러

  • 컨트롤러란 파드들을 관리하는 역할

  • 웹 서비스처럼 오랜 시간동안 계속 실행되어야 하는 파드들을 관리할 때는 레플리케이션 컨트롤러, 레플리카 세트, 디플로이먼트

  • 클러스터의 전체 노드에 같은 파드를 실행할 때는 데몬 세트

  • 상태가 없는 앱을 실행하는데 사용하는 컨테이너를 상태가 있는 앱을 실행할 때 사용하도록 만드는 스테이트풀세트

  • 1회성 작접을 할 때 사용하는 , 주기적인 배치 작업을 실행할 때 사용하는 크론잡

  • 이처럼 다양한 목적에 맞게 사용할 수 있는 컨트롤러가 있다는 것이 쿠버네티스의 큰 장점


# 레플리케이션 컨트롤러(Replication Controller)

  • 쿠버네티스 프로젝트의 초기부터 있었던 가장 기본적인 컨트롤러
  • 지정한 숫자만큼의 파드가 항상 클러스터 안에서 실행되도록 관리
  • 요즘에는 비슷한 역할을 하는 레플리카세트를 사용

# 레플리카세트(Replicaset)

  • 레플리카세트는 레플레케이션 컨트롤러의 발전형으로, 레플리케이션 컨트롤러와 같은 동작을 하지만, 집합 기반의 셀렉터(in, notin, exists)를 지원하는 차이점 존재

  • 레플리케이션 컨트롤러는 kubectl에서 rolling-update 옵션을 사용할 수 있지만 레플리카세트는 사용할 수 없다는 차이 존재

  • 레플리카세트를 사용하는데 rolling-update 옵션이 필요할 때는 디플로이먼트 사용

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: nginx-replicaset
spec:
  template:
    metadata:
      name: nginx-replicaset
      labels:
        app: nginx-replicaset # selector에서 쓰일 이름
    spec:
      containers:
      - name: nginx-replicaset
        image: nginx
        ports:
        - containerPort: 80
  replicas: 3 # 유지할 파드의 개수
  selector:
    matchLabels:
      app: nginx-replicaset # 어떤 레이블의 파드를 선택해서 관리할지 설정

# 레플리카세트와 파드의 연관 관계

  • 파드는 레이블 기준으로 관리하므로 레플리카세트와 파드는 느슨하게 결합되어 있어, 수정, 삭제, 생성에 용이함

  • 레플리카세트 삭제를 파드에 영향을 안 주고 삭제시킬 수 있음

    $ kubectl delete replicaset nginx-replicaset --cascade=false
    

# 디플로이먼트(Deployment)

  • 쿠버네티스에서 상태가 없는 앱을 배포할 때 사용하는 가장 기본적인 컨트롤러
  • 디플로이먼트는 레플리카세트를 관리하면서 앱 배포를 더 세밀하게 관리
  • 단순히 실행시켜야 할 파드 개수를 유지하는 것뿐 아니라 앱을 배포할 때 롤링 업데이트하거나, 앱 배포 도중 잠시 멈췄다 다시 배포할 수 있음
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx-deployment
spec:
  replicas: 3 # 실행할 파드의 수 설정
  selector:
    matchLabels:
      app: nginx-deployment # metadata.labels.app 과 같은 값을 설정 
  template:
    metadata:
      labels:
        app: nginx-deployment
    spec:
      containers:
      - name: nginx-deployment # 실제 사용하려는 컨테이너 이름
        image: nginx # 컨테이너 이미지
        ports:
        - containerPort: 80 # 포트

# 디플로이먼트 수정

  • 디플로이먼트 설정을 변경할 때마다 새로운 레플리카세트가 생성되고 그에 맞게 파드가 변경됨
$ kubectl set image deployment/nginx-deployment nginx-deployment=nginx:1.191
$ kubectl edit deploy nginx-deployment
# 편집기 시작
# 편집기 종료 후
deployment.extentions/nginx-deployment edited

# 디플로이먼트 롤백하기

# 정보 확인
$ kubectl rollout history deploy nginx-deployment	

# 상세 내용 확인
$ kubectl rollout history deploy nginx-deployment --revision=3

# 현재 리비전을 되돌림
$ kubcetl rollout undo deploy nginx-deployment

# 특정 리비전(3)으로 실행 중인 파드 되돌리기
$ kubectl rollout undo deploy nginx-deployment --to-revision=3
  • 되돌릴 수 있는 리비전 숫자는 디플로이먼트의 템플릿의 .spec.revisionHistoryLimit 필드 값(default: 10)

# 파드 개수 조정하기

  • 실행 중인 디플로이먼트의 파드 개수를 조정하려면 kubectl scale 명령 실행
$ kubectl scale deploy nginx-deployment --replicas=5

# 디플로이먼트 배포 정리, 배포 재개, 재시작하기

  • kubectl rollout 명령을 이용해서 진행 중인 배포를 잠시 멈췄다가 다시 시작할 수 있음
# 업데이트 멈추기
$ kubectl rollout pause deploy/nginx-deployment

# 재개
$ kubectl rollout resume deploy/nginx-deployment

# 디플로이먼트 상태

  • 배포 중에는 디플로이먼트 상태가 변함

# 진행(Progressing)

  • 디플로이먼트가 새로운 레플리카세트를 만들 때
  • 디플로이먼트가 새로운 레플리카세트의 파드 개수를 늘릴 때
  • 디플로이먼트가 예전 레플리카세트의 파드 개수를 줄일 때
  • 새로운 파드가 준비 상태가 되거나 이용 가능한 상태가 되었을 때

# 완료(Complete)

  • 디플로이먼트가 관리하는 모든 레플리카세트가 업데이 완료되었을 때
  • 모든 레플리카세트가 사용 가능해졌을 때
  • 예전 레플리카세트가 모두 종료되었을 때

# 실패(Fail)

  • 쿼터 부족
  • readinessProbe 진단 실패
  • 컨테이너 이미지 가져오기 에러
  • 권한 부족
  • 제한 범위 초과
  • 앱 실행 조건을 잘못 지정
$ kubectl decribe deploy nginx-deployment
Conditions:
	Type				Status		Reason
	----				------		------
	Available   True	    MinimunReplicasAvailable
	Progressing	False 	  ProgressDeadlineExceeded

# 데몬세트

  • 데몬세트는 클러스터 전체 노드에 특정 파드를 실행할 때 사용하는 컨트롤러
  • 클러스터 안에 새롭게 노드가 추가되었을 때 데몬세트가 자동으로 해당 노드에 파드 실행
  • 데몬세트트 보통 로그 수집기를 실행하거나 노드를 모니터링하는 모니터링용 데몬 등 클러스터 전체에 항상 실행시켜두어야 하는 파드에 사용
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd-elasticsearch
  namespace: kube-system # 관리용 파드나 설정에 해당하므로 kube-system 네임스페이스 설정
  labels:	# 오브젝트를 식별하는 레이블
    k8s-app: fluentd-logging
spec:
  selector:
    matchLabels:
      name: fluentd-elasticsearch
  updateStrategy:
    type: RollingUpdate # Ondelete와 RollingUpdate 두 가지 값중 하나 선택
  template:
    metadata:
      labels:
        name: fluentd-elasticsearch
    spec:
      containers:
      - name: fluentd-elasticsearch
        image: fluent/fluentd-kubernetes-daemonset:elasticsearch
        env:
        - name: testenv
          value: value
        resources:
          limits:
            memory: 200Mi
          requests:
            cpu: 100m
            memory: 200Mi

# 스테이트풀세트

  • 스테이트풀세트는 상태가 있는 파드들을 관리하는 컨트롤러
  • 볼륨을 사용해서 특정 데이터를 저장한 후 파드를 재시작했을 때 해당 데이터를 유지
  • 여러 개의 파드 사이에 순서를 지정해서 실행되도록 할 수도 있음
apiVersion: v1 # 스테이트풀세트에서 사용할 서비스 설정 
kind: Service
metadata:
  name: nginx-statefulset-service
  labels:
    app: nginx-statefulset-service
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: nginx-statefulset-service
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web # 스테이트풀세트의 이름
spec:
  selector:
    matchLabels:
      app: nginx-statefulset
  serviceName: "nginx-statefulset-service"
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx-statefulset
    spec:
      terminationGracePeriodSeconds: 10 # 그레이스풀의 대기 시간 설정
      containers:
      - name: nginx-statefulset
        image: nginx
        ports:
        - containerPort: 80
          name: web%
  • 그레이스풀(gracefull): 실행 중인 프로세스를 종료할 때 바로 종료하는 것이 아니라 하던 작업을 마무리하고 정상적으로 종료하는 것을 의미

  • .spec.podManagement Policy 필드를 이용해 순서를 없앨 수도 있음


# 잡(Job)

  • 잡은 실행된 후 종료해야 하는 성격의 작업을 실행시킬 때 사용하는 컨트롤러
  • 특정 개수만큼의 파드를 정상적으로 실행 종료함을 보장함
  • 파드 실행 실패, 하드웨어 장애 발생, 노드 재시작 등 문제가 발생하면 다시 파드 실행
  • 잡 하나가 파드 여러 개 실행 가능
apiVersion: batch/v1 # 잡이 사용하는 버전
kind: Job
metadata:
  name: pi
spec:
  template:
    spec:
      containers:
      - name: pi
        image: perl
        command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"] # 원주율 계산 펄(perl) 명령
      restartPolicy: Never # 항상 성공으로 끝나도록 설정(OnFailure: 비정상적으로 실행 종료된 파드 관리)
  backoffLimit: 4 # 최대 몇 번까지 재시작할 것인지 설정

# 잡 병렬설 관리

  • 잡 하나가 몇 개의 파드를 동시에 실행할지를 '잡 병렬성'이라고 함

# 잡의 종류

# 단일 잡

  • 파드 하나만 실행
  • 파드가 정상적으로 실행 종료(파드 생명 주기가 Succeeded)되면 잡 실행을 완료
  • .spec.completions.spec.parallelism 필드를 설정하지 않음

# 완료 개수가 있는 병렬 잡

  • .spec.completions 필드 값으로 양수를 설정. 필드 값이 1이면 정상적으로 실행 종료된 파드가 1개만 생겨도 잡이 완료
  • .spec.parallelism 필드는 설정하지 않거나 기본값인 1로 설정

# 워크 큐가 있는 병렬 잡

  • .spec.completions 필드는 설정하지 않고, .spec.parallelism 필드는 양수로 설정
  • 파드 각각은 정상적으로 실행 종료됐는지를 독립적으로 결정 가능
  • 대기열에 있는 작업들이 모두 동시에 실행될 수 있음
  • 파드 하나라도 정상적으로 실행 종료되면 새로운 파드가 실행되지 않음
  • 최소한 파드 1개가 정상적으로 종료된 후 모든 파드가 실행 종료되면, 잡이 정상적으로 종료됨
  • 파드 1개가 정상적으로 실행 종료되면 다른 파드는 더 이상 동작하지 않거나 어떤 작업 처리 결과를 내지 않음

# 잡 패턴

  • 잡에서 파드를 병렬로 실행했을 때 파드 각각이 서로 통신하면서 동작하지 않음

# 잡의 일반적인 사용 패턴

  • 잡을 생성하는 오버헤드가 크기 때문에 작업마다 잡을 하나씩 생성해 사용하는 것보다는 모든 작업을 관리하는 잡 하나를 사용하는 것이 좋음
  • 작업 개수만큼의 파드를 생성하는 것보다 파드 하나가 여러 개의 작업을 처리하는 것이 좋음
  • 워크 큐를 사용한다면 카프카나 RabbitMQ 같은 큐 서비스로 워크 큐를 구현하도록 깆ㄴ 프로그램이나 컨테이너를 수정해야함

# 크론잡(CronJob)

  • 크론잡은 잡을 시간 기준으로 관리하도록 생성
  • 지정한 시간에 한번만 잡을 실행하거나 지정한 시간동안 주기적으로 잡을 반복 실행 가능

# Referenses

  • 쿠버네티스 입문 - 90가지 예제로 배우는 컨테이너 관리 자동화 표준 / 동양북스
Last Updated: 8/12/2020, 1:33:42 PM